package com.browsesoft.resource;

import java.io.Serializable;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import org.w3c.dom.Element;

import com.browsesoft.EntityManager;
import com.browsesoft.ManagerGroup;
import com.browsesoft.Tools;
import com.browsesoft.baseadapter.AdvancedSimpleEntity;
import com.browsesoft.dbtools.DBTools;
import com.browsesoft.log.OperateLog;
import com.browsesoft.user.User;

/**
 * 基本资源，从资源接口实现
 */
public abstract class BasicResource extends AdvancedSimpleEntity implements Resource, Serializable {
	// 子资源
	private LinkedList children = new LinkedList();

	// 父
	protected Resource parent = null;

	// 父ID
	protected String parentID = null;

	// 权限列表
	protected transient LinkedList rights = new LinkedList();

	// 资源对应的编辑模板名称
	protected String templateName = null;

	public BasicResource() {
	}

	public BasicResource(Hashtable attr) {
		this.attributes.putAll(attr);
	}

	// 设置府资源
	public void setParent(Resource res) {
		this.parent = res;
		if (res == null) {
			this.getAttributes().put("parentid", "");
		} else {
			this.getAttributes().put("parentid", parent.getID());
		}
	}

	// 得到父资源
	public Resource getParent() {
		return this.parent;
	}

	/**
	 * 添加子资源
	 * 
	 * @param res
	 *            要添加的子资源
	 */
	public void addChild(Resource res) {
		// 如果新加资源没有位置
		if (res.getPosition() == 0) {
			// 设置新加资源位置为最后资源位置加1
			res.setPosition(this.getPositionOfLastChild() + 1);
		}
		// 添加资源
		this.addByPosition((BasicResource) res);
		res.setParent(this);
	}

	/**
	 * 根据对象的位置插入对象
	 */
	private void addByPosition(BasicResource res) {
		// 得到对象在链表中的插入位置
		int pos = this.indexByPosition(res);
		// 如果找到了
		if (pos != -1) {
			// 插入对象
			this.children.add(pos, res);
		}
		// 否则
		else {
			// 在链表尾部增加
			this.children.add(res);
		}
	}

	/**
	 * 得到资源应当插入的位置
	 */
	private int indexByPosition(BasicResource res) {
		// 对于每一个子
		Iterator iter = this.children.iterator();
		for (int i = 0; iter.hasNext(); i++) {
			BasicResource item = (BasicResource) iter.next();
			// 如果位置大于给定位置
			if (item.getPosition() > res.getPosition()) {
				// 返回该对象
				return i;
			}
		}
		return -1;
	}

	/**
	 * 得到最后一项子的位置
	 * 
	 * @return 最后一项子的位置，如果没有子，为0
	 */
	private int getPositionOfLastChild() {
		// 得到子的个数
		int size = children.size();
		// 如果有子
		if (size > 0) {
			// 返回最后一项子资源位置
			Resource last = (Resource) this.children.getLast();
			return last.getPosition();
		}
		// 否则
		else {
			// 返回0
			return 0;
		}
	}

	/**
	 * 移走子资源
	 * 
	 */
	public void removeChild(Resource child) {
		this.children.remove(child);
		child.setParent(null);
	}

	// 得到资源类型
	public String getType() {
		return (String) this.getAttributes().get("resourcetype");
	}

	// 设置资源类型
	public void setType(String type) {
		this.attributes.put("resourcetype", type);
	}

	/**
	 * 得到位置
	 * 
	 * @return 位置，新建的位置为0
	 */
	public int getPosition() {
		try {
			return Integer.parseInt((String) this.getAttributes().get(
					"position"));
		} catch (NumberFormatException e) {
			return 0;
		}
	}

	// 设置位置
	public void setPosition(int pos) {
		this.attributes.put("position", Integer.toString(pos));
	}

	// 得到资源ID
	public String getID() {
		return (String) this.attributes.get("id");
	}

	/**
	 * 取得资源对应的编辑木板名称
	 * 
	 * @return
	 */
	public String getTemplateName() {
		return (String) this.getAttributes().get("templatename");
	}

	/**
	 * 设置资源对应的编辑木板名称
	 * 
	 */
	public void setTemplateName(String name) {
		this.templateName = (String) this.attributes.get("templatename");
		if (this.templateName == null || this.templateName.equals("")) {
			this.templateName = name;
			this.attributes.put("templatename", templateName);
		}
	}

	public LinkedList RightsToString(LinkedList rightList) {
		LinkedList list = new LinkedList();
		for (int i = 0; i < rightList.size(); i++) {
		}
		return list;
	}

	// 添加权限
	public void addRight(Right r) {
		if (r == null) {
			throw new RuntimeException("权限为空");
		}
		this.rights.add(r);
	}

	public void addRightByResource(Resource res) {
		Right right = new Right(res);
		this.rights.add(right);
		RightManager rightManager = RightManager.getRightManager();
		rightManager.addRight(right);
	}

	// 移走权限
	public void removeRight(Right r) {
		this.rights.remove(r);
	}

	public void removeRightByResource(Resource res) {
		for (int i = 0; i < rights.size(); i++) {
			Right right = (Right) rights.get(i);
			Resource resource = right.getResource();
			if (resource == res) {
				rights.remove(right);
				break;
			}
		}
	}

	public void removeRightByResourceAndType(Resource res, RightType type) {
		for (int i = 0; i < rights.size(); i++) {
			Right right = (Right) rights.get(i);
			String rightType = right.getType().getType();
			Resource resource = right.getResource();
			if (resource == res && rightType.equals(type.getType())) {
				rights.remove(right);
				break;
			}
		}
	}

	// 获得权限列表
	public LinkedList getRights() {
		try {
			LinkedList result = new LinkedList();
			result.addAll(LicensePolicyTool.getRights(this));
			return result;
		} catch (RuntimeException e) {
			throw e;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 装载资源之间的关系 1 找到父资源，根据父ID 2 找到子资源，根据子ID 3 找到权限，根据权限ID 这样的话，资源在数据库中的必须的三个字段
	 * childrenid，parentid, rightid
	 */
	public void createRelation() {
		Object obj = null;
		try {
			// 得到父节点
			Resource parent = this.searchParent();
			// 如果父节点存在
			if (parent != null) {
				// 设置父节点
				parent.addChild(this);
			}
			// 得到所有权限id
			RightManager rightManager = RightManager.getRightManager();
			String rightID = (String) this.getAttributes().get("rightid");
			// 对于每一个权限id
			Iterator iter = Tools.stringToLinkedList(rightID).iterator();
			while (iter.hasNext()) {
				String item = (String) iter.next();
				// 将得到的权限添加给资源
				Right right = rightManager.getRight(item);
				if (right == null) {
					throw new RuntimeException("取权限错误:"
							+ this.getAttributes().get("name"));
				}
				this.addRight(right);
			}
		} catch (ClassCastException e) {
			throw new RuntimeException("child is:" + obj.getClass().toString()
					+ " parentid is:" + this.getID() + " parentclass is:"
					+ this.getClass().getName());
		} catch (Exception ae) {
			ae.printStackTrace();
		}
	}

	private Resource searchParent() {
		Resource result;
		// 得到父节点
		String parentID = (String) this.getAttributes().get("parentid");
		result = (Resource) EntityManager.getInstance().getObject(parentID);
		return result;
	}

	/**
	 * 设置用户
	 */
	public void setLoginUser(User user) {
		this.loginUser = user;
	}

	// 更新自己，具体资源替换
	public void update() throws Exception {
		DBTools.update((String) this.getTableName(), getID(), attributes);
	}

	// 删除
	public void delete() throws Exception {
		// 判断是否可以删除
		if (this.getChildren().hasNext()) {
			throw new Exception("该资源拥有下属，不能删除");
		}
		// 从库中删除
		DBTools.delete(this.getTableName(), getID());
		// 从父组织中删除子组织
		Resource parent = this.getParent();
		if (parent != null) {
			getParent().removeChild(this);
		}
		EntityManager entitymanager = (EntityManager) ManagerGroup
				.getManagerGroup().getManager("entity");
		entitymanager.remove(this);
		RightManager rightManager = (RightManager) ManagerGroup
				.getManagerGroup().getManager("right");
		LinkedList list = rightManager.getRightsByResource(this);
		if (list.size() > 0) {
			while (list.iterator().hasNext()) {
				rightManager.remove((Right) list.iterator().next());
			}
		}
		if (loginUser != null) {
			// 写日志
			OperateLog operateLog = new OperateLog();
			operateLog.deleteLog(loginUser, this);
		}
	}

	/**
	 * 得到部门下的用户
	 * 
	 * @return
	 */
	public LinkedList getChildUser() {
		LinkedList temp = new LinkedList();
		Iterator list = this.getChildren();
		while (list.hasNext()) {
			Resource re = (Resource) list.next();
			if (re instanceof User) {
				temp.add((User) re);
			}
		}
		return temp;
	}

	/**
	 * 得到该资源下的所有子
	 * 
	 * @return Linkedlist
	 */
	public LinkedList getAllChildrens() {
		LinkedList childrenUsers = new LinkedList();
		Iterator iter = this.getChildren();
		// 对于每一个子
		while (iter.hasNext()) {
			Resource re = (Resource) iter.next();
			// 添加组织
			childrenUsers.add(re);
			// 添加组织下的所有用户
			childrenUsers.addAll(re.getAllChildrens());
		}
		return childrenUsers;
	}

	/**
	 * 得到该资源下的所有子不包括叶子结点
	 * 
	 * @return Linkedlist
	 */
	public LinkedList getChildrensNoLeaf() {
		LinkedList childrenUsers = new LinkedList();
		Iterator iter = this.getChildren();
		// 对于每一个子
		while (iter.hasNext()) {
			Resource re = (Resource) iter.next();
			if (re.getChildren().hasNext()) {
				// 添加组织
				childrenUsers.add(re);
				// 添加组织下的所有用户
				childrenUsers.addAll(re.getAllChildrens());
			}
		}
		return childrenUsers;
	}

	public String toString() {
		return (String) this.attributes.get("name");
	}

	public abstract String getTableName();

	/**
	 * 得到该资源下某类资源的所有资源，包括所有后代以及这些后代的父亲
	 */
	public LinkedList getResourceTreeByType(String type) {
		// 得到该资源下该类型的所有资源
		LinkedList result = this.getAllChildByType(type);
		// 得到结果的所有父亲
		LinkedList parents = this.getAllAncenstor(result);
		// 返回资源与父亲的和
		Tools.add(result, parents);
		return result;
	}

	/**
	 * 取得该资源下所有某类型的孩子，不包括后代
	 */
	public LinkedList getChildrenByType(String type) {
		LinkedList result = new LinkedList();
		// 对于所有孩子
		Iterator iter = this.getChildren();
		while (iter.hasNext()) {
			BasicResource item = (BasicResource) iter.next();
			// 是给定类型的资源
			if (item.getType().equals(type)) {
				result.add(item);
			}
		}
		return result;
	}

	/**
	 * 取得该资源下某种类型的所有后代，即使父亲不是，也要取得子,包括自己。
	 */
	public LinkedList getAllChildByType(String type) {
		LinkedList result = new LinkedList();
		// 如果自己是
		if (this.getType().equals(type)) {
			// 把自己添加到结果中
			result.add(this);
		}
		// 取得所有孩子
		Iterator iter = this.getChildren();
		while (iter.hasNext()) {
			BasicResource child = (BasicResource) iter.next();
			// 把孩子的结果添加到结果中
			result.addAll(child.getAllChildByType(type));
		}
		return result;
	}

	/**
	 * 得到给定类型的所以子，包括后代
	 * 
	 * @param type
	 * @return
	 */
	public LinkedList getSpecialResByType(String type) {
		LinkedList list = new LinkedList();
		Iterator ite = this.getChildren();
		while (ite.hasNext()) {
			BasicResource res = (BasicResource) ite.next();
			if (res.getType().equals(type)) {
				list.add(res);
			} else {
				list.addAll(res.getSpecialResByType(type));
			}
		}
		return list;
	}

	/**
	 * 得到资源给定属性的全路径
	 */
	public String getPath(String field) {
		String result = ResourceTool.getFullPathName(this, field, 0);
		return result;
	}

	/**
	 * 得到资源的全路径
	 * 
	 * @return 全路径
	 */
	@Deprecated
	public String getPath() {
		String temp = (String) this.getAttributes().get("name") + ".";
		Resource res = this;
		while (res.getParent() != null) {
			res = res.getParent();
			temp = temp + res.getAttributes().get("name") + ".";
		}
		return temp.substring(0, temp.length() - 1);
	}

	/**
	 * 取得本资源有权访问的资源列表
	 * 
	 * @return 资源列表
	 */
	public LinkedList getResourcesByRight() throws Exception {
		LinkedList temp = new LinkedList();
		Iterator it = this.getRights().iterator();
		while (it.hasNext()) {
			Right right = (Right) it.next();
			Resource r = right.getResource();
			if (r != null) {
				temp.add(r);
			}
		}
		return temp;
	}

	/**
	 * 取得本资源有权访问的资源树的所有资源列表，所有子资源要添加父资源
	 * 
	 * @return 有权访问的资源树的所有资源列表
	 */
	public LinkedList getResourceTreeByRight() throws Exception {
		// 取得所有有权访问的资源
		LinkedList list = this.getResourcesByRight();
		LinkedList parents = this.getAllAncenstor(list);
		Tools.add(list, parents);
		return list;
	}

	/**
	 * 得到列表中所有资源的所有祖先
	 */
	private LinkedList getAllAncenstor(LinkedList list) {
		LinkedList result = new LinkedList();
		// 对于给定列表中的每一个资源
		Iterator iter = list.iterator();
		while (iter.hasNext()) {
			BasicResource item = (BasicResource) iter.next();
			// 将该资源的所有祖先添加到结果中
			LinkedList ances = item.getAncenstorResource();
			Tools.add(result, ances);
		}
		return result;
	}

	/**
	 * 得到该资源的所有祖先资源，包括自己
	 */
	private LinkedList getAncenstorResource() {
		LinkedList result = new LinkedList();
		Resource res = this;
		while (res != null) {
			// 添加资源
			result.add(res);
			// 找父亲
			res = res.getParent();
		}
		return result;
	}

	// 得到父亲和父亲以上某种类型的资源
	public Resource getSpecialResFormSelfToRoot(String type) {
		Resource r = this.getParent();
		Iterator ite = r.getChildren();
		while (ite.hasNext()) {
			Resource res = (Resource) ite.next();
			if (res.getType().equals(type)) {
				return res;
			} else if (!ite.hasNext()) {
				r = r.getParent();
				ite = r.getChildren();
			}
		}
		return null;
	}

	/**
	 * 得到资源到第几层的路径
	 */
	public String getPathWithLevel(int level) {
		String source = this.getPath();
		// 第一个.
		int start = source.lastIndexOf('.');
		for (int i = 0; i < level - 1; i++) {
			// 第二个.
			start = source.lastIndexOf('.', start - 1);
		}
		// 返回结果
		return source.substring(start + 1);
	}

	/**
	 * 得到祖先列表，不包括自己，顺序为从自己往上
	 */
	public LinkedList getParents() {
		LinkedList result = new LinkedList();
		Resource parent = this.getParent();
		while (parent != null) {
			result.add(parent);
			parent = parent.getParent();
		}
		return result;
	}
	/**
	 * 得到祖先列表的ID，不包括自己，顺序为从自己往上
	 */
	public LinkedList getParentsID() {
		LinkedList result = new LinkedList();
		Resource parent = this.getParent();
		while (parent != null) {
			result.add(parent.getID());
			parent = parent.getParent();
		}
		return result;
	}
	
	/**
	 * 得到祖先列表，不包括自己和根，顺序为从自己往上
	 * 
	 * @return 列表
	 */
	public LinkedList getParentsWithoutRoot() {
		LinkedList result = new LinkedList();
		Resource parent = this.getParent();
		while (parent != null) {
			if (parent.getParent() != null) {
				result.add(parent);
			}
			parent = parent.getParent();
		}
		return result;
	}

	/**
	 * 得到第几层父亲，0代表根
	 */
	public Resource getParentByLevel(int level) {
		// 得到祖先列表
		LinkedList list = this.getParents();
		// 从后面取第level层父亲
		return (Resource) list.get(list.size() - level - 1);
	}

	/**
	 * 得到当前资源下的最后一级
	 */
	public LinkedList getLeafByType(String type) {
		LinkedList result = new LinkedList();
		// 取得所有孩子
		LinkedList list = this.getAllChildrenByType(type);
		Iterator iter = list.iterator();
		// 对于每一个孩子
		while (iter.hasNext()) {
			// 取得直接孩子
			BasicResource item = (BasicResource) iter.next();
			LinkedList link = item.getChildrenByType(type);
			// 如果没有孩子
			if (link.size() == 0) {
				result.add(item);
			}
		}
		return result;
	}

	/**
	 * 取得该资源下某种类型的所有后代，即使父亲不是，也要取得子,不包括自己。
	 * 
	 * @param type
	 *            类型
	 * @return 所有后代
	 */
	public LinkedList getAllChildrenByType(String type) {
		LinkedList result = new LinkedList();
		// 取得所有孩子
		Iterator iter = this.getChildren();
		while (iter.hasNext()) {
			BasicResource child = (BasicResource) iter.next();
			// 把孩子的结果添加到结果中
			result.addAll(child.getAllChildByType(type));
		}
		return result;
	}
	
	// 得到任意属性值
	public String getCondition(String condition) {
		return (String) this.getAttributes().get(condition);
	}

	public void sychronDelete() {
		this.deleteRelation();
		EntityManager.getInstance().remove(this);
	}

	public void sychronUpdate(Hashtable attributes) {
		// 断开关系
		this.deleteRelation();
		this.attributes = attributes;
		this.createRelation();
	}

	protected void deleteRelation() {
		if (parent != null) {
			this.parent.removeChild(this);
		}
	}

	/**
	 * 得到所有子的迭代
	 */
	public Iterator getChildren() {
		return this.children.iterator();
	}

	/**
	 * 返回子的列表
	 * @return
	 */
	public List getChildrenList() {
		return this.children;
	}

	/**
	 * 子资源换位
	 */
	public void switchPostion(Resource res1, Resource res2) {
		// 在链表中交换
		int index1 = this.children.indexOf(res1);
		int index2 = this.children.indexOf(res2);
		this.children.set(index1, res2);
		this.children.set(index2, res1);
		// 交换数据库表示
		int pos1 = res1.getPosition();
		int pos2 = res2.getPosition();
		res1.setPosition(pos2);
		res2.setPosition(pos1);
		try {
			res1.update();
			res2.update();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
	
	protected String getEntityType(Element e) {
		return "resource";
	}

	/**
	 * 取得第一个给定属性不为空的父
	 * @param name 属性名
	 * @return
	 */
	public Resource getParentHasAttr(String name) {
		Resource parent = this.getParent();
		while(parent != null) {
			String value = (String) parent.getAttributes().get(name);
			if (value != null && !value.trim().equals("")) {
				return parent;
			}
			parent = parent.getParent();
		}
		return null;
	}

	/**
	 * 取得第一个匹配的给定类型的祖先
	 * @param type
	 * @return
	 */
	public Resource getParentByType(String type) {
		Resource parent = this.getParent();
		while(parent != null) {
			if (parent.getType().equals(type)) {
				return parent;
			}
			parent = parent.getParent();
		}
		return null;
	}

	/**
	 * 取得给定名称的子
	 */
	public Resource getChildByName(String name) {
		for(Object obj : this.children) {
			Resource res = (Resource)obj;
			if(res.getAttributes().get("name").equals(name)) {
				return res;
			}
		}
		return null;
	}
}